home *** CD-ROM | disk | FTP | other *** search
- /* This is the c file that implements the action for this screen saver.
- See GraphicsModule.c for infomation on how to write your own.
-
- First Version Andrew Armstrong
-
- © 1995 Berkeley Systems Inc.
- */
-
- /*
- ** TAB SIZE = 4 spaces
- */
-
- /*
- ** TO DO:
- ** * Multiple monitors
- ** * Make the pixmap point right to the screen for Apple HD Accel
- ** * Make the sliders work in demo mode
- ** * Handle case where they are not installed (draw error message with WWW Address)
- **
- ** FUTURE DIRECTIONS
- ** * cutsie-ass names on the sliders
- */
-
- #define FAKE_QD3D_NOT_INSTALLED
-
-
- #if 0
- #pragma mark INCLUDES
- #endif
-
- /*
- ** PROJECT INCLUDES
- */
- #include "QD3DModule.h"
- #include "QD3DErrorModule.h"
- #include "Q3ADUtilities.h"
-
- /*
- ** ANSI INCLUDES
- */
- #include <math.h>
- #include <assert.h>
- #include <stdlib.h>
-
- /*
- ** MAC INCLUDES
- */
- #include <Quickdraw.h>
- #include <QDOffscreen.h>
- #include <CodeFragments.h>
-
- /*
- ** MISC INCLUDES
- */
- #include <QD3DGeometry.h>
- #include <QD3DTransform.h>
- #include <QD3DMath.h>
- #include <QD3DCamera.h>
- #include <QD3DLight.h>
- #include <QD3DGroup.h>
-
- #if 0
- #pragma mark CONSTANTS
- #endif
-
- /*
- ** CONSTANTS
- */
- #define kSize 1.0
- #define kSpace 1.0
- #define kLongSize (sizeof(long))
-
- #define kADParam_Speed 0
- #define kADParam_NumBoxes 1
- #define kADParam_PaneSize 2
- #define kADParam_Dithered 3
-
- #if 0
- #pragma mark GLOBALS
- #endif
-
- /*
- ** GLOBALS
- */
-
- float gPaneSizeTable[4] = {0.25, 0.50, 0.75, 1.0};
- TQ3Boolean gHasQuickDraw3D = kQ3False;
- long gBestMonitor = 0;
- long gDrawNow = true;
-
- #if 0
- #pragma mark PRIVATE STRUCTURES
- #endif
-
- typedef struct iTQ3ADModule
- {
- TQ3ViewObject view;
- TQ3ShaderObject shader;
- float paneSize;
- long numRows;
- TQ3ADOffscreen *offscreen;
-
- } iTQ3ADModule;
-
-
-
- #if 0
- #pragma mark PRIVATE FUNCTION DECLARATIONS
- #endif
-
- /*
- ** PRIVATE FUNCTIONS
- */
- static TQ3Status iQ3ADModule_ZeroOut(
- TQ3ADModule *ioModule);
-
- static TQ3CameraObject iQ3ADModule_NewCamera(
- long numRows);
-
- static TQ3GroupObject iQ3ADModule_NewLightGroup(
- long numRows);
-
- static TQ3Status iQ3ADModule_Submit(
- TQ3ADModule *ioModule);
-
-
- #if 0
- #pragma mark -
- #endif
-
- /******************************************************************************
- ** **
- ** PUBLIC FUNCTION DEFINITIONS **
- ** **
- *****************************************************************************/
-
- /*===========================================================================*\
- *
- * Routine: DoInitialize()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- OSErr DoInitialize(Handle *storage, RgnHandle blankRgn, GMParamBlockPtr params)
- {
- mUnused(blankRgn);
- mUnused(params);
-
-
- gBestMonitor = Q3ADUtility_GetBestMonitor(params->monitors);
-
- /*
- ** Check to see if we have access to QuickDraw 3D
- */
- gHasQuickDraw3D = ((long)Q3Initialize != kUnresolvedCFragSymbolAddress) ?
- kQ3True :
- kQ3False ;
-
- #ifdef FAKE_QD3D_NOT_INSTALLED
-
- gHasQuickDraw3D = kQ3False;
-
- #endif
-
- if (gHasQuickDraw3D == kQ3True) {
-
- /*
- ** We've got it!
- ** Create the QD3D module
- */
- Q3Initialize();
- *storage = (Handle)Q3ADModule_New(params);
-
- } else {
-
- /*
- ** We don't got it.
- ** Create the QD3D error module which doesn't require
- ** QD3D but is still kinda cool
- */
- *storage = (Handle)Q3ADErrorModule_New(params);
-
- }
-
- if (*storage)
- {
- return noErr;
- }
- else return ModuleError;
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: DoClose()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- OSErr DoClose(Handle storage,RgnHandle blankRgn,GMParamBlockPtr params)
- {
- mUnused(blankRgn);
- mUnused(params);
-
- if (gHasQuickDraw3D == kQ3True) {
-
- /*
- ** Dispose of the QD3D module
- */
- if (storage)
- Q3ADModule_Dispose((TQ3ADModule**)storage);
- Q3Exit();
-
- } else {
-
- /*
- ** Dispose of the error module
- */
- if (storage)
- Q3ADErrorModule_Dispose((TQ3ADErrorModule**)storage);
-
- }
- return noErr;
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: DoBlank()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- OSErr DoBlank(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params)
- {
- mUnused(storage);
- mUnused(blankRgn);
- mUnused(params);
-
- // Simply blanks out the area that we are going to draw in.
- FillRgn(blankRgn, (ConstPatternParam) ¶ms->qdGlobalsCopy->qdBlack);
-
- // If your were going to set a custom palette, now would be a good time.
- // Doing it when the screen is black elimates the palette flash
-
- return noErr;
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: DoDrawFrame()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- OSErr DoDrawFrame(Handle storage,RgnHandle blankRgn,GMParamBlockPtr params)
- {
- OSErr err;
- long i = 0;
- long privateSynch;
- mUnused(blankRgn);
- mUnused(params);
-
- privateSynch = params->monitors->monitorList[gBestMonitor].synchFlag;
-
- if ( (privateSynch == false) && (gDrawNow == true))
- gDrawNow = false;
- else if ( (privateSynch == true) && (gDrawNow == false))
- gDrawNow = true;
-
- if (gDrawNow == false)
- return noErr;
-
- if (gHasQuickDraw3D == kQ3True) {
- /*
- ** We're only supposed to draw one frame here but that makes my
- ** Powerbook jerky
- */
- for (i = 0; i < 1; i++) {
-
- err = TQ3Status_to_OSErr(
- Q3ADModule_Draw(
- *(TQ3ADModule**)storage)
- );
- if (err != noErr)
- return err;
- }
-
- } else {
-
- /*
- ** Dispose of the error module
- */
- if (storage)
- err = TQ3Status_to_OSErr(
- Q3ADErrorModule_Draw(*(TQ3ADErrorModule**)storage)
- );
-
- if (err != noErr)
- return err;
- }
-
- return err;
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: DoSetUp()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- OSErr DoSetUp(RgnHandle blankRgn,short message,GMParamBlockPtr params)
- {
- mUnused(blankRgn);
- mUnused(message);
- mUnused(params);
-
- return noErr;
- }
-
-
-
- #if 0
- #pragma mark -
- #endif
-
- /*===========================================================================*\
- *
- * Routine: Q3ADModule_New()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3ADModule **Q3ADModule_New(GMParamBlockPtr params)
- {
- TQ3RendererObject theRenderer = NULL;
- TQ3DrawContextObject theDrawContext = NULL;
- TQ3CameraObject theCamera = NULL;
- TQ3GroupObject theLightGroup = NULL;
-
- TQ3Status status = kQ3Success;
-
- TQ3ADModule **outModule = NULL;
-
- Rect monitorRect, tempRect, alignedRect;
-
- unsigned long halfWidth,
- halfHeight;
-
- assert(params);
-
- mBailIfNULL_(outModule = (TQ3ADModule **)NewHandle(sizeof(TQ3ADModule)));
- HLock((Handle) outModule);
-
- mBailIfNot_(iQ3ADModule_ZeroOut(*outModule));
-
- (**outModule).paneSize =
- gPaneSizeTable[params->controlValues[kADParam_PaneSize] - 1];
-
- (**outModule).numRows =
- (long)(params->controlValues[kADParam_NumBoxes] / 10.0) + 1;
-
-
- /*
- ** OFFSCREEN
- */
-
- /*
- ** Set up the destination rect
- */
-
- monitorRect = Q3ADUtility_GetRectOfBestMonitor(params->monitors);
-
- halfWidth = (monitorRect.right - monitorRect.left) * 0.5;
- halfHeight = (monitorRect.bottom - monitorRect.top) * 0.5;
-
- /*
- ** Scale the rect to the percentage of the screen that we want
- */
- SetRect(
- &tempRect,
- (1.0 - (**outModule).paneSize) * halfWidth,
- (1.0 - (**outModule).paneSize) * halfHeight,
- (1.0 + (**outModule).paneSize) * halfWidth,
- (1.0 + (**outModule).paneSize) * halfHeight);
-
- /*
- ** Place it in the center of our chosen monitor
- */
- OffsetRect(
- &tempRect,
- params->qdGlobalsCopy->qdThePort->portRect.left + monitorRect.left,
- params->qdGlobalsCopy->qdThePort->portRect.left + monitorRect.top);
-
- /*
- ** We align this on byte boundaries because CopyBits can blit it faster.
- ** We do this so that if anything, it shrinks the rect a bit to
- ** make sure it stays on the screen.
- */
- SetRect(
- &alignedRect,
- tempRect.left - (tempRect.left % kLongSize),
- tempRect.top + (kLongSize - (tempRect.top % kLongSize)),
- tempRect.right + (kLongSize - (tempRect.right % kLongSize)),
- tempRect.bottom - (tempRect.bottom % kLongSize));
-
- mBailIfNULL_((**outModule).view = Q3View_New());
-
- mBailIfNULL_((**outModule).offscreen = Offscreen_New(
- (CGrafPtr)params->qdGlobalsCopy->qdThePort,
- (const Rect *) &alignedRect,
- params->controlValues[kADParam_Dithered]));
- /*
- ** DRAW CONTEXT
- */
- mBailIfNULL_(theDrawContext = Offscreen_NewPixmapDrawContext(
- (**outModule).offscreen));
-
- mBailIfNot_(Q3View_SetDrawContext(
- (**outModule).view,
- theDrawContext));
-
- /*
- ** RENDERER
- */
- mBailIfNULL_(theRenderer = Q3ADUtility_NewRenderer());
-
- mBailIfNot_(Q3View_SetRenderer(
- (**outModule).view,
- theRenderer));
-
- /*
- ** CAMERA
- */
- mBailIfNULL_(theCamera = iQ3ADModule_NewCamera((**outModule).numRows));
-
- mBailIfNot_(Q3View_SetCamera(
- (**outModule).view,
- theCamera));
-
- /*
- ** LIGHT GROUP
- */
- mBailIfNULL_(theLightGroup = iQ3ADModule_NewLightGroup((**outModule).numRows));
-
- mBailIfNot_(Q3View_SetLightGroup(
- (**outModule).view,
- theLightGroup));
-
- /*
- ** SHADER
- */
- mBailIfNULL_((**outModule).shader = Q3ADUtility_NewShader());
-
- bail:
-
- if (theRenderer)
- Q3Object_Dispose(theRenderer);
-
- if (theDrawContext)
- Q3Object_Dispose(theDrawContext);
-
- if (theCamera)
- Q3Object_Dispose(theCamera);
-
- if (theLightGroup)
- Q3Object_Dispose(theLightGroup);
-
- if (status == kQ3Failure)
- if(outModule) {
- Q3ADModule_Dispose(outModule);
- outModule = NULL;
- }
-
- return outModule;
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: Q3ADModule_Dispose()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3Status Q3ADModule_Dispose(TQ3ADModule **inModule)
- {
- assert(inModule);
- if ((**inModule).view)
- Q3Object_Dispose((**inModule).view);
- if ((**inModule).shader)
- Q3Object_Dispose((**inModule).shader);
- if ((**inModule).offscreen)
- Offscreen_Dispose((**inModule).offscreen);
- DisposeHandle((Handle)inModule);
- return kQ3Success;
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: Q3ADModule_Draw()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3Status Q3ADModule_Draw(
- TQ3ADModule *inModule)
- {
- TQ3Status status = kQ3Success;
- TQ3ViewStatus viewStatus = kQ3ViewStatusRetraverse;
-
- mBailIfNot_(Q3View_StartRendering(inModule->view));
- do {
-
- iQ3ADModule_Submit(inModule);
-
- } while ((viewStatus = Q3View_EndRendering(inModule->view)) == kQ3ViewStatusRetraverse);
-
- if (viewStatus == kQ3ViewStatusDone)
- mBailIfNot_(Offscreen_Blit(inModule->offscreen));
-
- bail:
-
- return status;
- }
-
-
-
- #if 0
- #pragma mark -
- #endif
-
- /******************************************************************************
- ** **
- ** PUBLIC FUNCTION DEFINITIONS **
- ** **
- *****************************************************************************/
-
- /*===========================================================================*\
- *
- * Routine: iQ3ADModule_ZeroOut()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3Status iQ3ADModule_ZeroOut(TQ3ADModule *inModule)
- {
- assert(inModule);
-
- inModule->view = NULL;
- inModule->shader = NULL;
- inModule->paneSize = 1.0;
- inModule->numRows = 8;
- inModule->offscreen = NULL;
- return kQ3Success;
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: iQ3ADModule_NewCamera()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3CameraObject iQ3ADModule_NewCamera(long numRows)
- {
- TQ3ViewAngleAspectCameraData perspectiveData;
-
- TQ3Point3D from = { 11.5, 11.5, 15.0 };
- TQ3Point3D to = { 11.5, 11.5, 0.0 };
- TQ3Vector3D up = { 0.0, 1.0, 0.0 };
-
- float fieldOfView = 1.0;
- float hither = 0.001;
- float yon = 1000;
-
- up.x = 0.0;
- up.y = 1.0;
- up.z = 0.0;
-
-
- from.x = ((float) (kSize + kSpace) * numRows - kSpace) / 2.0;
- from.y = from.x;
- from.z = ((float) (kSize + kSpace) * numRows + (3 * kSpace));
-
- to.x = from.x;
- to.y = to.x;
-
- #define mCData perspectiveData.cameraData
-
- mCData.placement.cameraLocation = from;
- mCData.placement.pointOfInterest = to;
- mCData.placement.upVector = up;
-
- mCData.range.hither = hither;
- mCData.range.yon = yon;
-
- mCData.viewPort.origin.x = -1.0;
- mCData.viewPort.origin.y = 1.0;
- mCData.viewPort.width = 2.0;
- mCData.viewPort.height = 2.0;
-
-
- perspectiveData.fov = fieldOfView;
- perspectiveData.aspectRatioXToY = 1.0;
-
- return Q3ViewAngleAspectCamera_New(&perspectiveData);
-
- #undef mCData
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: iQ3ADModule_NewLightGroup()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3GroupObject iQ3ADModule_NewLightGroup(long numRows)
- {
- TQ3GroupObject lightGroup = NULL;
- TQ3LightData lightData;
- TQ3PointLightData pointLightData;
- TQ3DirectionalLightData directionalLightData;
- TQ3LightObject ambientLight = NULL, pointLight = NULL, fillLight = NULL;
- TQ3Point3D pointLocation = { -10.0, 0.0, 0.0 };
- TQ3Vector3D fillDirection = { 10.0, 0.0, 10.0 };
- TQ3ColorRGB whiteLight = { 1.0, 1.0, 1.0 };
- TQ3Status status = kQ3Success;
-
- // Set up light data for ambient light. This light data will be used for point and fill
- // light also.
-
- lightData.isOn = kQ3True;
- lightData.color = whiteLight;
-
- // Create ambient light.
- lightData.brightness = .5;
- mBailIfNULL_(ambientLight = Q3AmbientLight_New(&lightData));
-
- // Create point light.
- lightData.brightness = 1.0;
- pointLightData.lightData = lightData;
- pointLightData.castsShadows = kQ3False;
- pointLightData.attenuation = kQ3AttenuationTypeNone;
- pointLocation.y = pointLocation.z = pointLocation.x = ((float) (kSize + kSpace) * numRows - kSpace) / 2.0;
- pointLightData.location = pointLocation;
- mBailIfNULL_(pointLight = Q3PointLight_New(&pointLightData));
-
- // Create fill light.
- lightData.brightness = .2;
- directionalLightData.lightData = lightData;
- directionalLightData.castsShadows = kQ3False;
- directionalLightData.direction = fillDirection;
- mBailIfNULL_(fillLight = Q3DirectionalLight_New(&directionalLightData));
-
- // Create light group and add each of the lights into the group.
- mBailIfNULL_(lightGroup = Q3LightGroup_New());
-
- mBailIfNot_(Q3Group_AddObject(lightGroup, ambientLight));
-
- mBailIfNot_(Q3Group_AddObject(lightGroup, pointLight));
-
- // mBailIfNot_(Q3Group_AddObject(lightGroup, fillLight));
-
- bail:
- if (ambientLight)
- Q3Object_Dispose( ambientLight ) ;
-
- if (pointLight)
- Q3Object_Dispose( pointLight ) ;
-
- if (fillLight)
- Q3Object_Dispose( fillLight ) ;
-
- if (status == kQ3Failure)
- {
- if (lightGroup)
- Q3Object_Dispose( lightGroup ) ;
-
- lightGroup = NULL;
- }
- return lightGroup;
- }
-
-
-
- /*===========================================================================*\
- *
- * Routine: iQ3ADModule_Submit()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3Status iQ3ADModule_Submit(
- TQ3ADModule *inModule)
- {
- TQ3BoxData myBoxData;
- TQ3RotateAboutAxisTransformData rotate;
-
- float pulse1, pulse2, pulse3, pulse4,
- sinpulse1, sinpulse2, sinpulse3,
- randpulse1, randpulse2, randpulse3,
- scaler;
-
- float rotationOrigin =
- ((float)(kSize + kSpace) *
- inModule->numRows - kSpace) / 2.0;
-
- TQ3ColorRGB diffuse;
- int idx, idy;
-
- TQ3Status status = kQ3Success;
-
- assert(inModule->view);
- assert(inModule->shader);
-
-
- /*
- ** Initialize our utilities (this just gets a current tick count)
- ** to base it's further calculations on
- */
- mQ3ADUtility_Begin();
-
- /*
- ** Grab off some pulses from the utilities (the parameters are in ticks)
- ** If you pass in prime numbers, the pulses will never sync up
- ** so you get this great organic kind of thing
- **
- ** Did you ever read "A Wrinkle In Time?" by Madeline L'Engle?
- ** There's this great scene with this huge pulsating brain
- ** which gets everyone in the whole city to sync up with it.
- ** After a while, the whole town is sucked in to the rhythm and it
- ** takes over their minds.
- */
- pulse1 = mQ3ADUtility_GetPulse(600);
- pulse2 = mQ3ADUtility_GetPulse(407);
- pulse3 = mQ3ADUtility_GetPulse(1423);
- pulse4 = mQ3ADUtility_GetPulse(750);
-
- /*
- ** Run 'em through a sin wave
- */
- sinpulse1 = sin(pulse1);
- sinpulse2 = sin(pulse2);
- sinpulse3 = sin(pulse3);
-
- randpulse1 = sinpulse2 * sinpulse3;
- randpulse2 = sinpulse1 * sinpulse2;
- randpulse3 = sinpulse1 * sinpulse3;
-
- scaler = fabs(sinpulse1) * (kSpace + kSize);
-
- diffuse.r = Q3ADUtility_GetNumInRange(sinpulse1, 1.0, 0.5);
- diffuse.g = Q3ADUtility_GetNumInRange(sinpulse2, 1.0, 0.5);
- diffuse.b = Q3ADUtility_GetNumInRange(sinpulse3, 1.0, 0.5);
-
-
- myBoxData.faceAttributeSet = NULL;
- myBoxData.boxAttributeSet = NULL;
-
- Q3Point3D_Set(
- &rotate.origin,
- rotationOrigin,
- rotationOrigin,
- 0);
-
- Q3Vector3D_Set(
- &rotate.orientation,
- sinpulse3,
- randpulse1,
- randpulse2);
-
- rotate.radians = pulse1;
-
- Q3Vector3D_Set(
- &myBoxData.orientation,
- Q3ADUtility_GetNumInRange(sinpulse2, 0.0, 0.25) * 2,
- Q3ADUtility_GetNumInRange(sinpulse2, 1.0, 0.50) * 2,
- 0);
-
- Q3Vector3D_Set(
- &myBoxData.majorAxis,
- 0,
- Q3ADUtility_GetNumInRange(randpulse3, 0.0, 0.25) * 2,
- Q3ADUtility_GetNumInRange(scaler, 1.0, 0.50) * 2);
-
- Q3Vector3D_Set(
- &myBoxData.minorAxis,
- Q3ADUtility_GetNumInRange(randpulse1, 1.0, 0.50) * 2,
- 0,
- Q3ADUtility_GetNumInRange(randpulse2, 0.0, 0.25) * 2);
-
-
- Q3BackfacingStyle_Submit(
- kQ3BackfacingStyleRemove,
- inModule->view);
-
- Q3Object_Submit(
- inModule->shader,
- inModule->view);
-
- Q3RotateAboutAxisTransform_Submit(
- &rotate,
- inModule->view);
-
- Q3Attribute_Submit(
- kQ3AttributeTypeDiffuseColor,
- &diffuse,
- inModule->view);
-
- for (idx = 0; idx < inModule->numRows; idx++) {
-
- for (idy = 0; idy < inModule->numRows; idy++) {
-
- Q3Point3D_Set(&myBoxData.origin, idx * (kSize + kSpace),
- idy * (kSize + kSpace), 0);
-
- Q3Box_Submit(&myBoxData, inModule->view);
- }
- }
-
- bail:
-
- mQ3ADUtility_End();
-
- return status;
- }
-
-
-